package gl.java.umsp.router;

import gl.java.umsp.event.Event;
import gl.java.umsp.event.EventPublisher;
import io.netty.channel.Channel;
import lombok.extern.log4j.Log4j;
import lombok.extern.slf4j.Slf4j;

import java.util.Map;
import java.util.Observable;
import java.util.Observer;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;

/**
 * 通道路由表.双map保存channel与ID的对应关系.
 */
@Slf4j
public class ChannelRouter {
    private Map<Channel, Integer> mChannelMap;
    private Map<Integer, Channel> mUserIDMap;

    private ChannelRouter() {
        mChannelMap = new ConcurrentHashMap();
        mUserIDMap = new ConcurrentHashMap();
    }

    public void registerRouter(int id, Channel channel) {
        mChannelMap.put(channel, id);
        mUserIDMap.put(id, channel);
        log.info("Channel registerRouter, id:" + id + " channel:" + channel);
    }


    private static class SingleHolder {
        final static ChannelRouter holder = new ChannelRouter();
    }

    public static ChannelRouter getInstance() {
        return SingleHolder.holder;
    }

    public int unRegisterRouter(Channel ctx) {
        if (ctx == null) {
            return 0;
        }
        if (mChannelMap.containsKey(ctx)) {
            Integer key = mChannelMap.remove(ctx);
            if (mUserIDMap.containsKey(key)) {
                mUserIDMap.remove(key);
                EventPublisher.pub(Event.USER_OFF_LINE, Event.buildUserEvent(key));
                log.info("Channel unRegister,key:" + key + " channel:" + ctx.toString());
                return key;
            } else {
                log.warn("ChannelRouter Map is not exist the Integer Key:" + key);
            }
        } else {
            log.warn("ChannelRouter Map is not exist the Channel:" + ctx);
        }
        return 0;
    }

    public Channel getChannel(int id) {
        return mUserIDMap.get(id);
    }

    public boolean containsKey(int id) {
        return mUserIDMap.containsKey(id);
    }

    public Integer getID(Channel ctx) {
        final Integer integer = mChannelMap.get(ctx);
        return integer == null ? 0 : integer;
    }

    public Set<Channel> getAllChannel() {
        return mChannelMap.keySet();
    }
}
